<?php

namespace App\Kuafu\Product\Validate;

use App\Exceptions\CustomValidateException;
use App\Http\Validate\AbstractBaseValidate;
use App\Kuafu\Base\Enum\DBEnum;
use App\Kuafu\Base\Model\BaseModel;
use App\Kuafu\Config\Model\ConfigModel;
use App\Kuafu\Product\Enum\CodeEnum;
use App\Kuafu\Product\Enum\ProductCodeEnum;
use App\Kuafu\Product\Exceptions\ProductException;
use App\Kuafu\Product\Model\Product;
use App\Kuafu\Product\Resources\ProductResource;
use App\Kuafu\Shop\Model\ShopProductStatus;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use PHP_CodeSniffer\Reports\Code;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class ProductNewValidate extends AbstractBaseValidate
{

    /**
     * @inheritDoc
     */
    function getRules(): array
    {
        // TODO: Implement getRules() method.
        return [
            "id"                      => [
                "required",
                "int",
                Rule::exists("products", "id")
                    ->where("menuId", 0)
                    ->where("isDeleted", 0)
            ],
            "categoryId"              => ["required", "int", Rule::exists("category", "id")],
            "kind"                    => self::intInValidateBuild(true, CodeEnum::KIND_MAP),
            "type"                    => self::intInValidateBuild(true, CodeEnum::TYPE_PRODUCT_TYPE_TEXT),
            "name"                    => self::stringValidateBuild(true, 18, 1,
                function () { return Rule::unique("products", "name")->where("isDeleted", 0); }),
            "desc"                    => self::stringValidateBuild(true, 25, 1),
            "imageUrl"                => self::stringValidateBuild(true, 255, 1),
            "unit"                    => ["required_if:type," . CodeEnum::PRODUCT_TYPE_SINGLE, "max:5"],
            "price"                   => self::intValidateBuild(true, 1000000000, 1),
            "costPrice"               => self::intValidateBuild(false, 1000000000),
            "vipPrice"                => self::intValidateBuild(false, 1000000000),
            "sort"                    => self::intValidateBuild(true, 1000000000),
            "isHot"                   => "required|bool",
            "isRecommend"             => "required|bool",
            "showPlatform"            => "required|int",
            "isMust"                  => "int|in:0,1",
            "productList"             => ["required_if:type," . CodeEnum::PRODUCT_TYPE_PACKAGE, "array", "min:1"],
            "productList.*.productId" => [
                "required_if:type," . CodeEnum::PRODUCT_TYPE_PACKAGE,
                "int"
            ],
            "productList.*.num"       => [
                "required_if:type," . CodeEnum::PRODUCT_TYPE_PACKAGE,
                "int",
                "min:1"
            ],
        ];
    }

    /**
     * @inheritDoc
     */
    function getAttributes(): array
    {
        // TODO: Implement getAttributes() method.
        return [
            "categoryId"              => "分类ID",
            "productList"             => "子菜品",
            "productList.*.productId" => "子菜品-菜品ID",
            "productList.*.num"       => "子菜品-菜品数量",
            "name"                    => "菜品名称",
            "desc"                    => "菜品描述",
            "imageUrl"                => "菜品图片",
            "price"                   => "菜品价格",
            "costPrice"               => "菜品成本价",
            "vipPrice"                => "菜品会员价格",
            "isMust"                  => "是否菜品必选",

        ];
    }

    /**
     * @inheritDoc
     */
    function registerValidateRules(): void
    {
        // TODO: Implement registerValidateRules() method.
    }

    /**
     * @inheritDoc
     */
    function getMessages(): array
    {
        // TODO: Implement getMessages() method.
        return [
            "id.exists" => "选定的商品已失效"
        ];
    }


    /**
     * 添加校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface|CustomValidateException
     */
    public static function merchantInsertValidate(array $params)
    {
        $instance = self::getInstance();
        return $instance->validate(
            ["name", "productList", "showPlatform", "price", "unit", 'imageUrl'],
            $params,
            [
                "showPlatform" => "required|int|in:0,1",
                'imageUrl'     => 'string',
            ],
            true,
            function (array $params) {
                if (!isset($params['imageUrl'])) {
                    $params['imageUrl'] = ConfigModel::query()
                                                     ->where('key', 'productPackageDefaultImg')
                                                     ->where('type', 'customerProduct')
                                                     ->pluck('value')->first();
                }
                return array_merge($params, [
                    "shopId"     => request()->header("shopId", 0),
                    "type"       => CodeEnum::PRODUCT_TYPE_PACKAGE,
                    "kind"       => CodeEnum::KIND_CUSTOMER,
                    "categoryId" => ConfigModel::query()
                                               ->where("key", "customProductCategoryId")
                                               ->where("type", "merchant")
                                               ->pluck("value")->first()
                ]);
            }
        );
    }

    /**
     * 编辑校验
     *
     * @param int $productId
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ProductException
     * @throws ValidationException
     */
    public static function merchantUpdateValidate(int $productId, array $params)
    {
        $product = Product::query()->where("id", $productId)->first();
        if (empty($product)) {
            throw new ProductException(ProductCodeEnum::ERR_PRODUCT_NOT_EXIST);
        }
        $validateFields = $validateExtraRules = [];
        switch ($product->kind) {
            case CodeEnum::KIND_CUSTOMER:
                switch ($product->type) {
                    case CodeEnum::PRODUCT_TYPE_SINGLE:
                        //自定义菜品：可以修改菜品售价、上架/下架、点餐小程序展示开关，单位不可编辑。
                        //新下发的自定义菜品默认下架状态，需要加盟商手动上架。
                        $validateFields     = ["price", "showPlatform", "isMust"];
                        $validateExtraRules = [
                            "showPlatform" => "required|int|in:0,1"
                        ];
                        break;
                    case CodeEnum::PRODUCT_TYPE_PACKAGE:
                        //自定义套餐：可以修改套餐名称、售价、单位、上架/下架、点餐小程序展示开关，分类默认 套餐 分类不可编辑，图片默认且不可编辑。
                        $validateFields     = ["name", "price", "showPlatform", "unit", "productList", "isMust", "imageUrl"];
                        $validateExtraRules = [
                            "name"         => self::stringValidateBuild(true, 25, 1,
                                function () use ($params, $productId) {
                                    return Rule::unique("products", "name")->ignore($productId, "id");
                                }),
                            "showPlatform" => "required|int|in:0,1",
                            'imageUrl'     => 'string',
                            "unit"         => ["required", "string", "max:5"],
                        ];
                        break;
                }
                break;
            case CodeEnum::KIND_NORMAL:
                //标准菜品：可以修改上架/下架、点餐小程序展示开关。新下发的标准商品默认上架状态。
                $validateFields     = ["showPlatform", "isMust"];
                $validateExtraRules = [
                    "showPlatform" => "required|int|in:0,1"
                ];
                break;
        }

        $instance = self::getInstance();
        return $instance->validate(
            $validateFields,
            collect($params)->only($validateFields)->toArray(),
            $validateExtraRules,
            true,
            function (array $params) use ($product) {
                $params["id"]     = $product->id;
                $params['isMust'] = $params['isMust'] ?? 0;
                return $params;
            }
        );
    }


    /**
     * 添加校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function webInsertValidate(array $params)
    {
        $instance = self::getInstance();
        $kind     = $params['kind'] ?? 0;
        return $instance->validate(
            collect($instance->getRules())->except(["id"])->keys()->toArray(),
            $params,
            [
                "name" => self::stringValidateBuild(true, 18, 1,
                    function () use ($kind) {
                        return Rule::unique("products", "name")->where('menuId', 0)
                                    ->where("isDeleted", 0)
                                   ->when($kind, function ($q) use ($kind) {
                                       $q->where('kind', $kind);
                                   });
                    }),
                "desc" => self::stringValidateBuild(false, 25, 1),
            ],
            true,
            function (array $params) {
                $params["isHot"]       = (int)$params["isHot"];
                $params["isRecommend"] = (int)$params["isRecommend"];
                if ($params["type"] == CodeEnum::PRODUCT_TYPE_SINGLE && $params["kind"] == CodeEnum::KIND_CUSTOMER) {
                    $params["status"] = DBEnum::STATUS_DOWN;
                }
                return $params;
            }
        );
    }


    /**
     * 添加校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function posInsertValidate(array $params)
    {
        $instance = self::getInstance();
        return $instance->validate(
            ["name", "unit", "type", "productList", "showPlatform", "price"],
            $params,
            null,
            true,
            function (array $params) {
                return array_merge($params, [
                    "imageUrl"   => ConfigModel::query()
                                               ->where("key", "productPackageDefaultImg")
                                               ->where("type", "customerProduct")
                                               ->pluck("value")->first(),
                    "shopId"     => request()->header("shopId", 0),
                    "kind"       => CodeEnum::KIND_CUSTOMER,
                    "categoryId" => ConfigModel::query()
                                               ->where("key", "customProductCategoryId")
                                               ->where("type", "merchant")
                                               ->pluck("value")->first()
                ]);
            }
        );
    }

    /**
     * 编辑校验
     *
     * @param int $productId
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ProductException
     * @throws ValidationException
     */
    public static function posUpdateValidate(int $productId, array $params)
    {
        $product = Product::query()->where("id", $productId)->first();
        if (empty($product)) {
            throw new ProductException(ProductCodeEnum::ERR_PRODUCT_NOT_EXIST);
        }
        $validateFields = $validateExtraRules = [];
        switch ($product->kind) {
            case CodeEnum::KIND_CUSTOMER:
                switch ($product->type) {
                    case CodeEnum::PRODUCT_TYPE_SINGLE:
                        //自定义菜品：可以修改菜品售价、上架/下架、点餐小程序展示开关，单位不可编辑。
                        //新下发的自定义菜品默认下架状态，需要加盟商手动上架。
                        $validateFields     = ["price", "showPlatform"];
                        $validateExtraRules = [
                            "showPlatform" => "required|int|in:0,1"
                        ];
                        break;
                    case CodeEnum::PRODUCT_TYPE_PACKAGE:
                        //自定义套餐：可以修改套餐名称、售价、单位、上架/下架、点餐小程序展示开关，分类默认 套餐 分类不可编辑，图片默认且不可编辑。
                        $validateFields     = ["name", "price", "showPlatform", "unit", "productList"];
                        $validateExtraRules = [
                            "name"         => self::stringValidateBuild(true, 25, 1,
                                function () use ($params, $productId) {
                                    return Rule::unique("products", "name")->ignore($productId, "id");
                                }),
                            "showPlatform" => "required|int|in:0,1",
                            "unit"         => ["required", "string", "max:5"],
                        ];
                        break;
                }
                break;
            case CodeEnum::KIND_NORMAL:
                //标准菜品：可以修改上架/下架、点餐小程序展示开关。新下发的标准商品默认上架状态。
                $validateFields     = ["showPlatform"];
                $validateExtraRules = [
                    "showPlatform" => "required|int|in:0,1"
                ];
                break;
        }

        $instance = self::getInstance();
        return $instance->validate(
            $validateFields,
            collect($params)->only($validateFields)->toArray(),
            $validateExtraRules,
            true,
            function (array $params) use ($product) {
                $params["id"] = $product->id;
                return $params;
            }
        );
    }

    /**
     * 编辑校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function updateValidate(array $params)
    {
        $instance = self::getInstance();
        $kind     = $params['kind'] ?? 0;
        return $instance->validate(
            collect($instance->getRules())->except(["kind"])->keys()->toArray(),
            $params,
            [
                "name" => self::stringValidateBuild(true, 25, 1,
                    function () use ($params, $kind) {
                        return Rule::unique("products", "name")->where('menuId', 0)
                                   ->where("isDeleted", 0)
                                   ->when($kind, function ($q) use ($kind) {
                                       $q->where('kind', $kind);
                                   })->ignore($params["id"], "id");

                    }),
                "desc" => self::stringValidateBuild(false, 25, 1),
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface|CustomValidateException
     */
    public static function detailValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id", "menuId"],
            $params,
            [
                "id"     => Rule::exists("products", "id")
                                ->where("menuId", 0)
                                ->where("isDeleted", 0),
                "menuId" => "sometimes|int|min:0"
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function merchantStatusValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id", "status"],
            $params,
            [
                'status' => 'nullable|integer|between:0,2'
            ]
        );
    }


    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function webStatusValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id", "status"],
            $params,
            [
                'status' => 'nullable|integer|between:0,2',
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function posStatusValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id", "status", "out"],
            $params,
            [
                'status' => 'nullable|integer|between:0,2',
                'out'    => 'nullable|integer|between:0,2',
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function posDeleteValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id"],
            $params,
            [
                Rule::exists("products", "id")->where("type", CodeEnum::PRODUCT_TYPE_PACKAGE)
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function merchantDeleteValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id"],
            $params,
            [
                Rule::exists("products", "id")->where("type", CodeEnum::PRODUCT_TYPE_PACKAGE)
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function webDeleteValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id"],
            $params,
            [
                Rule::exists("products", "id")
            ]
        );
    }
}
